﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
#if !DOT_NET
using Windows.Foundation.Collections;
#endif
#if NETFX_CORE
using Windows.UI.Xaml;

#else
using System.Windows;

#endif

namespace StyleMVVM.View
{
	public sealed class RegionCollection : IObservableVector<Region>
	{
		private WeakReference elementReference;
		private readonly List<Region> collection;

		public RegionCollection()
		{
			collection = new List<Region>();
		}

		public FrameworkElement Element
		{
			get
			{
				if (elementReference != null)
				{
					return elementReference.Target as FrameworkElement;
				}
				return null;
			}
			set
			{
				if (value != null)
				{
					elementReference = new WeakReference(value);
				}
				else
				{
					elementReference = null;
				}
			}
		}

		public IEnumerator<Region> GetEnumerator()
		{
			return collection.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		public void Add(Region item)
		{
			collection.Add(item);
			RaiseCollectionChanged(CollectionChange.ItemInserted, collection.Count - 1, new List<Region> { item });
		}

		public void Clear()
		{
			List<Region> oldList = new List<Region>(collection);
			collection.Clear();
			RaiseCollectionChanged(CollectionChange.Reset, 0, null, oldList);
		}

		public bool Contains(Region item)
		{
			return collection.Contains(item);
		}

		public void CopyTo(Region[] array, int arrayIndex)
		{
			collection.CopyTo(array, arrayIndex);
		}

		public bool Remove(Region item)
		{
			int index = IndexOf(item);

			if (collection.Remove(item))
			{
				RaiseCollectionChanged(CollectionChange.ItemRemoved, index, new List<Region> { item });

				return true;
			}

			return false;
		}

		public int Count
		{
			get { return collection.Count; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public int IndexOf(Region item)
		{
			return collection.IndexOf(item);
		}

		public void Insert(int index, Region item)
		{
			collection.Insert(index, item);
			RaiseCollectionChanged(CollectionChange.ItemInserted, index, new List<Region> { item }, null);
		}

		public void RemoveAt(int index)
		{
			Region oldRegion = collection[index];

			collection.RemoveAt(index);
			RaiseCollectionChanged(CollectionChange.ItemRemoved, index, null, new List<Region> { oldRegion });
		}

		public Region this[int index]
		{
			get { return collection[index]; }
			set
			{
				Region oldRegion = collection[index];

				collection[index] = value;
				RaiseCollectionChanged(CollectionChange.ItemChanged,
				                       index,
				                       new List<Region> { value },
				                       new List<Region> { oldRegion });
			}
		}

		public event VectorChangedEventHandler<Region> VectorChanged;

		private void RaiseCollectionChanged(CollectionChange change,
		                                    int index,
		                                    IEnumerable<Region> newRegions = null,
		                                    IEnumerable<Region> oldRegions = null)
		{
			if (oldRegions != null)
			{
				foreach (Region oldRegion in oldRegions)
				{
					oldRegion.Element = null;
				}
			}

			if (newRegions != null)
			{
				foreach (Region newRegion in newRegions)
				{
					newRegion.Element = Element;
				}
			}

			bool foundMain = false;

			for (int i = 0; i < this.Count; i++)
			{
				if (this[i].IsContainerMaster)
				{
					foundMain = true;
					break;
				}
			}

			if (!foundMain && Count > 0)
			{
				this[0].IsContainerMaster = true;
			}

			if (VectorChanged != null)
			{
				VectorChanged(this,
				              new RegionCollectionChanged
					              {
						              CollectionChange = change,
						              Index = (uint)index,
						              NewRegions = newRegions,
						              OldRegions = oldRegions
					              });
			}
		}
	}
}